// --------------------------------------------------------------------------------------------------------------------
// <copyright file="FeatureAdapter.cs" company="Collaboris Ltd.">
//   Copyright (c) Collaboris Ltd. All rights Reserved.
// </copyright>
// <summary>
//   Defines the FeatureReceiverBase type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Collaboris.Saf.Adapters
{
    using System;

    using Collaboris.Saf.Engine;
    using Collaboris.Saf.Engine.Report;
    using Collaboris.Utils;

    using Microsoft.SharePoint;

    using Repositories;

    /// <summary>
    /// Allows SAF to be called from a Feature
    /// </summary>
    /// <remarks>
    /// Please Note this class doesn't inherit from AdapterBase
    /// </remarks>
    public sealed class FeatureAdapter : AdapterBase
    {
        #region Constants and Fields

        /// <summary>
        /// The current feature name.
        /// </summary>
        private string currentFeatureName;

        /// <summary>
        /// The macro path.
        /// </summary>
        private string macroPath;

        /// <summary>
        /// The mode.
        /// </summary>
        private ProcessMode mode;

        /// <summary>
        /// The physical file name.
        /// </summary>
        private string physicalFileName;

        /// <summary>
        /// The properties.
        /// </summary>
        private SPFeatureReceiverProperties properties;

        #endregion

        #region Constructors and Destructors
        /// <summary>
        /// Initializes a new instance of the <see cref="FeatureAdapter"/> class.
        /// </summary>
        /// <param name="properties">
        /// The properties.
        /// </param>
        public FeatureAdapter(SPFeatureReceiverProperties properties)
        {
            this.InitAdapter(properties);
        }

        #endregion

        /*
        /// <summary>
        /// Initializes a new instance of the <see cref="FeatureAdapter"/> class.
        /// </summary>
        /// <param name="receiverProperties">
        /// The receiver properties.
        /// </param>
        public FeatureAdapter(SPFeatureReceiverProperties receiverProperties)
        {
            this.properties = receiverProperties;
            this.InitAdapter();
        }
        */
        #region Properties

        /// <summary>
        /// Gets or sets the Adapter String for the 
        /// current adapter.
        /// </summary>
        /// <value>The current directory.</value>
        public override string AdapterName
        {
            get
            {
                return "Feature";
            }
        }

        /// <summary>
        /// Stores a Reference to the Current 
        /// Feature ID
        /// </summary>
        public string CurrentFeatureName
        {
            get
            {
                return this.currentFeatureName;
            }
        }

        /// <summary>
        /// Gets or sets the macro path.
        /// </summary>
        /// <value>The macro path.</value>
        public string MacroPath
        {
            get
            {
                return this.macroPath;
            }

            set
            {
                this.macroPath = value;
            }
        }

        /// <summary>
        /// Gets or sets the current mode.
        /// </summary>
        /// <value>The current mode.</value>
        public override ProcessMode Mode
        {
            get
            {
                return this.mode;
            }

            set
            {
                this.mode = value;
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// A local run to call Map to EntityList and call the Run
        /// in the derived class.
        /// </summary>
        /// <param name="eventType">
        /// Type of the event.
        /// </param>
        public void ExecuteMacro(FeatureEvent eventType)
        {
            TraceHelper.TraceMethodStart(TraceSwitch, "FeatureAdapter", "Run");

            if (eventType == FeatureEvent.Activated)
            {
                this.Mode = ProcessMode.Do;
            }

            if (eventType == FeatureEvent.Deactivating)
            {
                this.Mode = ProcessMode.Undo;
            }
            
            // BalamuruganK - Code added to take multiple ActionsFile / MacroFile from the feature.            
            // TODO: Reverse the order for the Undo...
            foreach (SPFeatureProperty featureProperty in this.properties.Feature.Properties)
            {
                string propertyKey = featureProperty.Name;
                if (propertyKey.StartsWith("ActionsFile", StringComparison.OrdinalIgnoreCase)
                    ||
                    propertyKey.StartsWith("MacroFile", StringComparison.OrdinalIgnoreCase)
                    )
                {
                    string fileName = featureProperty.Value.ToString();
                    this.physicalFileName = fileName;
                    this.macroPath = this.properties.Definition.RootDirectory + "\\" + fileName;

                    try
                    {
                        // Note: InitAdapter function initialises rest of the property...
                        // TODO: Call Init here...
                        this.ExecuteMacro();
                    }
                    catch (Exception ex)
                    {
                        // TODO: Log error...
                        //TraceHelper.TraceError("Failed to execute the macro :{0} with the following exception :{1}.",fileName,ex.ToString());
                    }
                }
            }

            // Save the Report to disk
            TraceHelper.TraceMethodStart(TraceSwitch, "FeatureAdapter", "Run");
        }

        #endregion

        #region Helper Methods

        /// <summary>
        /// Called when the Adapter needs to add Placeholders
        /// from (its specific environment) to a SAF Macro.
        /// </summary>
        /// <param name="ctx">
        /// SafContext the context on which to add the shortcuts
        /// </param>
        protected override void AddProperties(SafContext ctx)
        {
            // Add the Features Dir to the 12!
            if (!string.IsNullOrEmpty(this.properties.Definition.RootDirectory))
            {
                ctx.ActionProperties.Add("FeatureDir", this.properties.Definition.RootDirectory, true);
            }

            // now add all the feature props too
            foreach (SPFeatureProperty featureProperty in this.properties.Feature.Properties)
            {
                ctx.ActionProperties.Add(featureProperty.Name, featureProperty.Value, true);
            }

        }

        /// <summary>
        /// Called when the Adapter Requires a Macro to be
        /// instatiated and returned.
        /// </summary>
        /// <param name="ctx">
        /// The SafContext.
        /// </param>
        /// <returns>
        /// An Instantiated Macro, created using Spring.Net
        /// </returns>
        protected override IMacro GetMacro(SafContext ctx)
        {
            // return Macro.Create(MacroPath, ctx);

            // Create the Macro from the string passed in on the Service.
            IMacro newMacro = MacroEngine.Create(this.MacroPath, ctx);

            return newMacro;
        }

        /// <summary>
        /// Gets the name of the macro file on disk.
        /// </summary>
        /// <returns>
        /// The get macro file name.
        /// </returns>
        protected override string GetMacroName()
        {
            return this.physicalFileName;
        }

        /// <summary>
        /// Gets the correct Macro Report from the
        /// location as specified by the Adapter.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <param name="reportName">
        /// The report Name.
        /// </param>
        /// <returns>
        /// </returns>
        protected override MacroReport GetReport(SafContext context, string reportName)
        {
            ValidationHelper.VerifyObjectArgument(context, "SafContext");
            ValidationHelper.VerifyStringArgument(reportName, "reportName");

            var repository = new FileReportRepository(this.CurrentDirectory);

            return repository.LoadObject(BuildReportName(reportName, this.mode));
        }

        /// <summary>
        /// Saves the <see cref="MacroReport"/> to disk.
        /// </summary>
        /// <param name="report">
        /// The report.
        /// </param>
        /// <param name="reportName">
        /// The report Name.
        /// </param>
        protected override void SaveReport(MacroReport report, string reportName)
        {
            ValidationHelper.VerifyObjectArgument(report, "report");

            var repository = new FileReportRepository(this.CurrentDirectory);

            repository.SaveObject(reportName, report);
        }

        /// <summary>
        /// Initialises the Adapter.
        /// </summary>
        /// <param name="properties">
        /// The properties.
        /// </param>
        private void InitAdapter(SPFeatureReceiverProperties properties)
        {
            ValidationHelper.VerifyObjectArgument(properties, "SPFeatureReceiverProperties");

            this.properties = properties;

            if (this.properties.Feature.Parent is SPWeb)
            {
                var web = this.properties.Feature.Parent as SPWeb;
                this.TargetUrl = web.Url;
            }

            if (this.properties.Feature.Parent is SPSite)
            {
                var site = this.properties.Feature.Parent as SPSite;
                this.TargetUrl = site.RootWeb.Url;
            }

            string fileName = string.Empty;
            if (this.properties.Feature.Properties["MacroFile"] != null)
            {
                fileName = this.properties.Feature.Properties["MacroFile"].Value;
            }
            else
            {
                if (this.properties.Feature.Properties["ActionsFile"] != null)
                {
                    fileName = this.properties.Feature.Properties["ActionsFile"].Value;
                }
            }

            this.physicalFileName = fileName;

            ValidationHelper.VerifyObjectArgument(this.properties.Definition, "SPFeatureReceiverProperties.Definition");

            this.macroPath = this.properties.Definition.RootDirectory + "\\" + fileName;
            this.currentFeatureName = this.properties.Feature.Definition.Name;
            this.CurrentDirectory = this.properties.Definition.RootDirectory;
            this.currentFeatureName = this.properties.Definition.DisplayName;
        }

        #endregion
    }
}